package com.wef.system.service.impl;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Hibernate;

import com.gfa4j.hibernate.BaseObject;
import com.gfa4j.service.impl.BaseServiceImpl;
import com.wef.system.entity.AclCondition;
import com.wef.system.entity.AclConfigEntry;
import com.wef.system.entity.AclPermission;
import com.wef.system.entity.Role;
import com.wef.system.service.AclPermissionService;

public class AclPermissionServiceImpl extends BaseServiceImpl implements
		AclPermissionService {

	public List<AclConfigEntry> loadAclConfigEntrys() {
		return loadAll(AclConfigEntry.class);
	}

	public AclPermission saveOrUpdateAclPermission(AclPermission aclPermission) {
		if (aclPermission.getRowStatus() == BaseObject.ROWSTATUS_ADDED) {
			return addAclPermission(aclPermission);
		} else if (aclPermission.getRowStatus() == BaseObject.ROWSTATUS_MODIFIED) {
			return updateAclPermission(aclPermission);
		} else if (aclPermission.getRowStatus() == BaseObject.ROWSTATUS_DELETED) {
			removeAclPermission(aclPermission);
			return null;
		}

		return null;
	}

	private void removeAclPermission(AclPermission aclPermission) {

		if (!aclPermission.getAclConditions().isEmpty()) {
			removeAclConditions(aclPermission.getAclConditions());
		}

		super.deleteObject(aclPermission);
	}

	private void removeAclConditions(Set<AclCondition> aclConditions) {
		for (AclCondition aclCondition : aclConditions) {
			if (!aclCondition.getChildConditions().isEmpty()) {
				removeAclConditions(aclCondition.getChildConditions());
			}
			super.deleteObject(aclCondition);
		}
	}

	private AclPermission updateAclPermission(AclPermission aclPermission) {
		AclPermission newAclPermission = (AclPermission) super.load(
				AclPermission.class, aclPermission.getAclPermissionId());

		if (!newAclPermission.getAclConditions().isEmpty()) {
			removeAclConditions(newAclPermission.getAclConditions());
			newAclPermission.getAclConditions().clear();
			super.getHibernateSession().flush();
		}

		newAclPermission.setCrudType(aclPermission.getCrudType());
		newAclPermission.setEntityName(aclPermission.getEntityName());
		newAclPermission.setRole(aclPermission.getRole());
		newAclPermission.setRowStatus(aclPermission.getRowStatus());

		for (AclCondition eachAclCondition : (Collection<AclCondition>) aclPermission
				.getAclConditions()) {
			newAclPermission.addAclCondition(addAclCondition(eachAclCondition));
		}

		super.updateObject(newAclPermission);
		return newAclPermission;
	}

	private AclPermission addAclPermission(AclPermission aclPermission) {

		AclPermission newAclPermission = new AclPermission();
		newAclPermission.setCrudType(aclPermission.getCrudType());
		newAclPermission.setEntityName(aclPermission.getEntityName());
		newAclPermission.setRole(aclPermission.getRole());
		newAclPermission.setRowStatus(aclPermission.getRowStatus());

		newAclPermission = (AclPermission) super.saveObject(newAclPermission);

		for (AclCondition eachAclCondition : (Collection<AclCondition>) aclPermission
				.getAclConditions()) {
			if (eachAclCondition.getParentCondition() != null)
				continue;
			newAclPermission.addAclCondition(addAclCondition(eachAclCondition));
		}

		return newAclPermission;
	}

	private AclCondition addAclCondition(AclCondition aclCondition) {
		AclCondition newAclCondition = new AclCondition();
		newAclCondition.setLogicNode(aclCondition.getLogicNode());
		newAclCondition.setPropertyName(aclCondition.getPropertyName());
		newAclCondition.setOperator(aclCondition.getOperator());
		newAclCondition.setValue(aclCondition.getValue());

		newAclCondition = (AclCondition) super.saveObject(newAclCondition);

		for (AclCondition childCondition : (Collection<AclCondition>) aclCondition
				.getChildConditions()) {
			newAclCondition.addChildCondition(addAclCondition(childCondition));
		}

		return newAclCondition;
	}

	public Role txRequiredCopyRolePermission(String targetRoleId,
			String sourceRoleId) {
		Role target = (Role) super.load(Role.class, targetRoleId);
		Role source = (Role) super.load(Role.class, sourceRoleId);

		for (AclPermission aclPermission : (Collection<AclPermission>) target
				.getAclPermissions()) {
			this.removeAclPermission(aclPermission);
		}
		target.getAclPermissions().clear();
		super.getHibernateSession().flush();

		for (AclPermission aclPermission : (Collection<AclPermission>) source
				.getAclPermissions()) {
			target.addAclPermission(addAclPermission(aclPermission));
		}

		return target;
	}

	@SuppressWarnings("unchecked")
	public List loadAllRoleAndAclPermission() {
		List listRoles = super.loadAll(Role.class);
		for (Iterator it = listRoles.iterator(); it.hasNext();) {
			Role role = (Role) it.next();
			Hibernate.initialize(role.getAclPermissions());
		}

		return listRoles;
	}
}
